package com.jbr.simplefoodplan.entities;

import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.KeyFactory;
import java.util.ArrayList;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.users.User;

import java.io.Serializable;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import static com.google.appengine.api.datastore.FetchOptions.Builder.*;

/**
 *
 * @author jbr
 */
@XmlRootElement(name = "dish")
@XmlAccessorType(XmlAccessType.NONE)
public final class Dish implements Serializable, SecurableEntity, Comparable<Dish> {

    private Entity entity;
    private boolean addUsagesInPlans;

    public Dish(Entity entity) {
        this.entity = entity;
    }

    public Dish() {
        this.entity = new Entity("dish");
    }

    @Override
    public Entity getEntity() {
        return this.entity;
    }

    public String getKey() {
        return KeyFactory.keyToString(entity.getKey());
    }


    @XmlElement
    public Long getId() {
        return entity.getKey().getId();
    }

    public void setId(Long id) {
        System.out.println("Setting id to " + id);
        if (id == null)
            return;
        try {
            entity = DatastoreServiceFactory.getDatastoreService()
                    .get(KeyFactory.createKey("dish", id));
            System.out.println("Entity found!");
        } catch (EntityNotFoundException ex) {
            throw new RuntimeException(ex);
        }
    }

    @XmlElement
    public String getName() {
        return (String)entity.getProperty("name");
    }

    public void setName(String name) {
         entity.setProperty("name", name);
    }

    @Override
    public User getUser() {
        return (User)entity.getProperty("user");
    }

    @Override
    public void setUser(User user) {
        entity.setProperty("user", user);
    }

    public boolean isAddUsagesInPlans() {
        return addUsagesInPlans;
    }

    public void setAddUsagesInPlans(boolean addUsagesInPlans) {
        this.addUsagesInPlans = addUsagesInPlans;
    }



    @XmlElement
    public Plan getLastUsage() {
        if (!addUsagesInPlans) return null;
        List<Plan> plans = getUsagesInPlans();
        if (!plans.isEmpty())
            return plans.get(0);
        return null;
    }

    @XmlElement
    public Integer getLastUsageInDays() {
        Plan lastPlan = getLastUsage();
        if (lastPlan != null) {
            LocalDate from = LocalDate.fromDateFields(lastPlan.getDate());
            LocalDate to = new LocalDate();
            Days daysBetween = Days.daysBetween(from, to);
            return daysBetween.getDays();
        }
        return null;

    }

    @XmlElement
    public List<Plan> getUsagesInPlans() {
        if (!addUsagesInPlans) return null;
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        Query q = new Query("plan");
        q.addFilter("dishId", Query.FilterOperator.EQUAL, getId());
        q.addSort("date",Query.SortDirection.DESCENDING);
        /*
        final String query = "select from " + Plan.class.getName() +
        " where dishId == dishIdParam order by date desc";
        Query q = Datastore.getPersistenceManager().newQuery(query);
        q.declareParameters("Long dishIdParam");
        List<Plan> plans = (List<Plan>) q.execute(id);
         *
         */
        PreparedQuery pq = datastore.prepare(q);
        List<Entity> entityList = pq.asList(withLimit(20));
        List<Plan> planList = new ArrayList(entityList.size());
        for (Entity e : entityList) {
            planList.add(new Plan(e));
        }
        return planList;
    }

    @Override
    public String toString() {
        return "Dish{" + "id=" + getId() + " user=" + getUser() + " name="
                + getName() + " addUsagesInPlans=" + addUsagesInPlans + '}';
    }

    @Override
    public int compareTo(Dish o) {
        if (getLastUsageInDays()==null)
            return -1;
        if (o.getLastUsageInDays()==null)
            return 1;
        return getLastUsageInDays().compareTo(o.getLastUsageInDays()*-1);
    }


}
